package com.xxwu.messagequeue.mqserver.core;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.xxwu.messagequeue.common.Consumer;
import com.xxwu.messagequeue.common.ConsumerEnv;
import lombok.Data;

import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 消息队列
 */
@Data
public class MSGQueue {

    //队列的身份标识
    private String name;

    //是否持久化
    private boolean durable = false;

    //是否自动删除
    private boolean autoDelete = false;

    //是否被一个消费者独占
    private boolean exclusive = false;

    //开启附加功能
    private HashMap<String, Object> argument = new HashMap<>();

    // 用来保存订阅该队列的消费者
    private List<ConsumerEnv> listeners = new ArrayList<>();
    // 使用记录变量实现消费者轮询的消费消息
    // 使用原子变量解决线程安全的问题
    private AtomicInteger indexConsumer = new AtomicInteger(0);

    // 添加消费者
    public void addConsumerEnv(ConsumerEnv consumerEnv) {
        listeners.add(consumerEnv);
    }
    // 挑选消费者对消息进行消费
    public ConsumerEnv getConsumerEnv() {
        if(listeners.isEmpty()){
            // 这个队列没有消费者订阅
            return null;
        }
        // 计算要取元素的下标
        int index = indexConsumer.intValue() % listeners.size();
        indexConsumer.incrementAndGet();
        return listeners.get(index);
    }

    // 这里也要对 HashMap 进行格式转换
    public void setArgument(String argumentJson) {
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            this.argument = objectMapper.readValue(argumentJson, new TypeReference<HashMap<String, Object>>() {});
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
    }
    public String getArgument() {
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            return objectMapper.writeValueAsString(argument);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return "{}";
    }
    public void setArgument(String argKey, String argValue) {
        argument.put(argKey, argValue);
    }
    public Object getArgument(String argKey) {
        return argument.get(argKey);
    }

    public void setArgument(HashMap<String, Object> argument) {
        this.argument = argument;
    }
}
